package project.order.weixi;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONObject;
import project.order.work.AccessTokenThread;

public class WxPayHelper {
    private HashMap<String, String> parameters = new HashMap<String, String>();

    private String AppId = AccessTokenThread.appid;
    private String jsapiTicket = AccessTokenThread.jsapi_ticket;

    /**
     * 就是paysignkey,支付请求key
     */
    private String AppKey = "Privatetaitorapassionformen12345";//18shandingZHI18181818shandingZHI

    private String SignType = "MD5";//SHA1

    /**
     * 财付通商户权限密钥key
     */
    private String PartnerKey = "Privatetaitorapassionformen12345";//

    
    
    public WxPayHelper(){
        /**
         * 银行通道，固定WX
         */
//        this.SetParameter("bank_type", "WX");
        /**
         * 商户号
         */
//        this.SetParameter("partner", "1226244201");
//        this.SetParameter("partner", "10062489");
        
        this.SetParameter("fee_type", "CNY");
        /**
         * 通知地址
         */
        this.SetParameter("notify_url", "http://www.mrshine.cn/root/public/orderAction!paySuccess.action");
//        this.SetParameter("input_charset", "UTF-8");
//        this.SetParameter("appid", AppId);
        this.SetParameter("mch_id", "10062489");
        this.SetParameter("trade_type", "JSAPI");
//        this.SetParameter("openid", "o5hCrjuIr_KRaOLE07JBURf0ZTLQ");
    }
/***********************************JS-sdk START****************************************************************/
    public String getJsAPI(String uri) throws SDKRuntimeException {
        HashMap<String, String> nativeObj = new HashMap<String, String>();
        if (CheckCftParameters() == false) {
            throw new SDKRuntimeException("生成getJsAPI参数缺失！");
        }
        nativeObj.put("noncestr", CommonUtil.CreateNoncestr());
        nativeObj.put("jsapi_ticket",jsapiTicket);
        nativeObj.put("timestamp", Long.toString(new Date().getTime() / 1000));
        nativeObj.put("url", uri);
        nativeObj.put("signature", GetJsAPISign(nativeObj));
        nativeObj.put("appId", AppId);
        System.out.println(JSONObject.fromObject(nativeObj).toString());
        return JSONObject.fromObject(nativeObj).toString();
   
    }
    public String GetJsAPISign(HashMap<String, String> bizObj) throws SDKRuntimeException {
        HashMap<String, String> bizParameters = new HashMap<String, String>();

        List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(bizObj.entrySet());

        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                return (o1.getKey()).toString().compareTo(o2.getKey());
            }
        });

        for (int i = 0; i < infoIds.size(); i++) {
            Map.Entry<String, String> item = infoIds.get(i);
            if (item.getKey() != "") {
//                bizParameters.put(item.getKey().toLowerCase(), item.getValue());
            	bizParameters.put(item.getKey(), item.getValue());
            }
        }

        String bizString = CommonUtil.FormatBizQueryParaMap(bizParameters, false);
        System.out.println("未加密前的："+bizString);

        return SHA1Util.Sha1(bizString);

    }
 /***********************************JS-sdk  END****************************************************************/  
    private Boolean CheckCftParameters() {
//        if (parameters.get("bank_type") == "" || parameters.get("body") == "" || parameters.get("partner") == ""
//                || parameters.get("out_trade_no") == "" || parameters.get("total_fee") == ""
//                || parameters.get("fee_type") == "" || parameters.get("notify_url") == null
//                || parameters.get("spbill_create_ip") == "" || parameters.get("input_charset") == "") {
//            return false;
//        }
        return true;
    }

    public String GetCftPackage() throws SDKRuntimeException {
        if ("" == PartnerKey) {
            throw new SDKRuntimeException("密钥不能为空！");
        }
        String unSignParaString = CommonUtil.FormatBizQueryParaMap(parameters, false);
        String paraString = CommonUtil.FormatBizQueryParaMap(parameters, true);
        return paraString + "&sign=" + MD5SignUtil.Sign(unSignParaString, PartnerKey);

    }

    public String GetBizSign(HashMap<String, String> bizObj) throws SDKRuntimeException {
        HashMap<String, String> bizParameters = new HashMap<String, String>();

        List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(bizObj.entrySet());

        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                return (o1.getKey()).toString().compareTo(o2.getKey());
            }
        });

        for (int i = 0; i < infoIds.size(); i++) {
            Map.Entry<String, String> item = infoIds.get(i);
            if (item.getKey() != "") {
//                bizParameters.put(item.getKey().toLowerCase(), item.getValue());
            	bizParameters.put(item.getKey(), item.getValue());
            }
        }

        if (AppKey == "") {
            throw new SDKRuntimeException("APPKEY为空！");
        }
//        bizParameters.put("appkey", AppKey);
//        bizParameters.put("key", AppKey);
        String bizString = CommonUtil.FormatBizQueryParaMap(bizParameters, false);
        // System.out.println(bizString);

//        return SHA1Util.Sha1(bizString);
        return MD5SignUtil.Sign(bizString, AppKey);
    }

    // 生成app支付请求json
    /*
     * { "appid":"wwwwb4f85f3a797777", "traceid":"crestxu", "noncestr":"111112222233333", "package":
     * "bank_type=WX&body=XXX&fee_type=1&input_charset=GBK&notify_url=http%3a%2f%2f www
     * .qq.com&out_trade_no=16642817866003386000&partner=1900000109&spbill_create_ip
     * =127.0.0.1&total_fee=1&sign=BEEF37AD19575D92E191C1E4B1474CA9", "timestamp":1381405298,
     * "app_signature":"53cca9d47b883bd4a5c85a9300df3da0cb48565c", "sign_method":"sha1" }
     */
    public String CreateAppPackage(String traceid) throws SDKRuntimeException {
        HashMap<String, String> nativeObj = new HashMap<String, String>();
        if (CheckCftParameters() == false) {
            throw new SDKRuntimeException("生成package参数缺失！");
        }
        nativeObj.put("appId", AppId);
        nativeObj.put("package", "prepay_id=wx201410272009395522657a690389285100");//GetCftPackage()
        nativeObj.put("timeStamp", Long.toString(new Date().getTime() / 1000));
        nativeObj.put("traceid", traceid);
        nativeObj.put("nonceStr", CommonUtil.CreateNoncestr());
        nativeObj.put("app_signature", GetBizSign(nativeObj));
        nativeObj.put("sign_method", SignType);
        return JSONObject.fromObject(nativeObj).toString();
    }

    // 生成jsapi支付请求json
    /*
     * "appId" : "wxf8b4f85f3a794e77", //公众号名称，由商户传入 "timeStamp" : "189026618", //时间戳这里随意使用了一个值 "nonceStr" :
     * "adssdasssd13d", //随机串 "package" : "bank_type=WX&body=XXX&fee_type=1&input_charset=GBK&notify_url=http%3a%2f
     * %2fwww.qq.com&out_trade_no=16642817866003386000&partner=1900000109& spbill_create_i
     * p=127.0.0.1&total_fee=1&sign=BEEF37AD19575D92E191C1E4B1474CA9", //扩展字段，由商户传入 "signType" : "SHA1", //微信签名方式:sha1
     * "paySign" : "7717231c335a05165b1874658306fa431fe9a0de" //微信签名
     */
    /**
    *@author Kenshinbo@163.com
    *@描述：package参数
    *@return
    *@throws SDKRuntimeException 
    *@version  WxPayHelper.java,v 1.1 Feb 10, 2015 10:28:17 PM KB
    */
    public String CreateBizPackage() throws SDKRuntimeException {
        HashMap<String, String> nativeObj = new HashMap<String, String>();
        if (CheckCftParameters() == false) {
            throw new SDKRuntimeException("生成package参数缺失！");
        }
        nativeObj.put("appId", AppId);
        nativeObj.put("timeStamp", Long.toString(new Date().getTime() / 1000));
        nativeObj.put("nonceStr", CommonUtil.CreateNoncestr());
        nativeObj.put("package", "prepay_id="+getPrepayId());
        nativeObj.put("signType", SignType);
        nativeObj.put("paySign", GetBizSign(nativeObj));
        System.out.println("交易参数："+JSONObject.fromObject(nativeObj).toString());
        return JSONObject.fromObject(nativeObj).toString();
   
    }
    public HashMap<String, String> CreateBizPackageMap() throws SDKRuntimeException {
        HashMap<String, String> nativeObj = new HashMap<String, String>();
        if (CheckCftParameters() == false) {
            throw new SDKRuntimeException("生成package参数缺失！");
        }
        nativeObj.put("appId", AppId);
        nativeObj.put("timeStamp", Long.toString(new Date().getTime() / 1000));
        nativeObj.put("nonceStr", CommonUtil.CreateNoncestr());
        nativeObj.put("package", "prepay_id="+getPrepayId());
        nativeObj.put("signType", SignType);
        nativeObj.put("paySign", GetBizSign(nativeObj));
        System.out.println("交易参数："+JSONObject.fromObject(nativeObj).toString());
        return nativeObj;
   
    }
    public String getPrepayId(){
    	String prepay_id = "";
    	//parameters 转xml
    	HashMap<String,String> signMap = new HashMap<String,String>();
    	try {
    		parameters.put("appid", AppId);
//    		signMap.put("mch_id", "10062489");
//    		signMap.put("nonce_str", CommonUtil.CreateNoncestr());
			parameters.put("nonce_str", CommonUtil.CreateNoncestr());
			parameters.put("sign", GetOrderSign(parameters));
			String orderXml = WxUtils.createXml2order(parameters);
	    	System.out.println("发出预下单xml:"+orderXml);
	    	//发送到接口获取预下单
	    	Map orderMap = WxUtils.httpRequestXml("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", orderXml);
	    	System.out.println("收到的预下单Map:"+orderMap.get("prepay_id"));
	    	if(null != orderMap.get("result_code")){
	    		System.out.println("result_code="+orderMap.get("result_code"));	    		
	    	}
	    	if(null != orderMap.get("return_msg")){
	    		System.out.println("return_msg="+orderMap.get("return_msg"));	    		
	    	}
	    	if(null != orderMap.get("err_code")){
	    		System.out.println("err_code="+orderMap.get("err_code"));	    		
	    	}
	    	if(null != orderMap.get("err_code_des")){
	    		System.out.println("err_code_des="+orderMap.get("err_code_des"));	    		
	    	}
	    	if(null != orderMap.get("prepay_id")){
	    		System.out.println("prepay_id="+orderMap.get("prepay_id"));	   
		    	prepay_id = orderMap.get("prepay_id").toString(); 		
	    	}
		} catch (SDKRuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	
    	return prepay_id;
    }
    /**
    *@author Kenshinbo@163.com
    *@描述：预下单签名
    *@param bizObj
    *@return
    *@throws SDKRuntimeException 
    *@version  WxPayHelper.java,v 1.1 Feb 11, 2015 12:00:21 AM KB
    */
    public String GetOrderSign(HashMap<String, String> bizObj) throws SDKRuntimeException {
        HashMap<String, String> bizParameters = new HashMap<String, String>();

        List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(bizObj.entrySet());

        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                return (o1.getKey()).toString().compareTo(o2.getKey());
            }
        });

        for (int i = 0; i < infoIds.size(); i++) {
            Map.Entry<String, String> item = infoIds.get(i);
            if (item.getKey() != "") {
//                bizParameters.put(item.getKey().toLowerCase(), item.getValue());
            	bizParameters.put(item.getKey(), item.getValue());
            }
        }

        if (AppKey == "") {
            throw new SDKRuntimeException("APPKEY为空！");
        }
        String bizString = "";
        
//		try {
//			bizString = new String(CommonUtil.FormatBizQueryParaMap(bizParameters, false).getBytes("ISO8859-1"),"gbk");
//			
//		} catch (UnsupportedEncodingException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		
		bizString = CommonUtil.FormatBizQueryParaMap(bizParameters, false);
		
        System.out.println("OrderSign="+bizString);
        return MD5SignUtil.Sign(bizString, AppKey);
    }
    
    // 生成原生支付url
    /*
     * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXXX&productid=XXXXXX&timestamp =XXXXXX&noncestr=XXXXXX
     */
    public String CreateNativeUrl(String productid) throws SDKRuntimeException {
        String bizString = "";
        try {
            HashMap<String, String> nativeObj = new HashMap<String, String>();
            nativeObj.put("appid", AppId);
            nativeObj.put("productid", URLEncoder.encode(productid, "utf-8"));
            nativeObj.put("timestamp", Long.toString(new Date().getTime() / 1000));
            nativeObj.put("noncestr", CommonUtil.CreateNoncestr());
            nativeObj.put("sign", GetBizSign(nativeObj));
            bizString = CommonUtil.FormatBizQueryParaMap(nativeObj, false);

        } catch (Exception e) {
            throw new SDKRuntimeException(e.getMessage());

        }
        return "weixin://wxpay/bizpayurl?" + bizString;
    }

    // 生成原生支付请求xml
    /*
     * <xml> <AppId><![CDATA[wwwwb4f85f3a797777]]></AppId>
     * <Package><![CDATA[a=1&url=http%3A%2F%2Fwww.qq.com]]></Package> <TimeStamp> 1369745073</TimeStamp>
     * <NonceStr><![CDATA[iuytxA0cH6PyTAVISB28]]></NonceStr> <RetCode>0</RetCode> <RetErrMsg><![CDATA[ok]]></ RetErrMsg>
     * <AppSignature><![CDATA[53cca9d47b883bd4a5c85a9300df3da0cb48565c]]> </AppSignature> <SignMethod><![CDATA[sha1]]></
     * SignMethod > </xml>
     */
    public String CreateNativePackage(String retcode, String reterrmsg) throws SDKRuntimeException {
        HashMap<String, String> nativeObj = new HashMap<String, String>();
        if (CheckCftParameters() == false && retcode == "0") {
            throw new SDKRuntimeException("生成package参数缺失！");
        }
        nativeObj.put("AppId", AppId);
        nativeObj.put("Package", GetCftPackage());
        nativeObj.put("TimeStamp", Long.toString(new Date().getTime() / 1000));
        nativeObj.put("RetCode", retcode);
        nativeObj.put("RetErrMsg", reterrmsg);
        nativeObj.put("NonceStr", CommonUtil.CreateNoncestr());
        nativeObj.put("AppSignature", GetBizSign(nativeObj));
        nativeObj.put("SignMethod", SignType);
        return CommonUtil.ArrayToXml(nativeObj);

    }
    
    public void SetAppId(String str) {
        AppId = str;
    }

    public void SetAppKey(String str) {
        AppKey = str;
    }

    public void SetSignType(String str) {
        SignType = str;
    }

    public void SetPartnerKey(String str) {
        PartnerKey = str;
    }

    public void SetParameter(String key, String value) {
        parameters.put(key, value);
    }

    public String GetParameter(String key) {
        return parameters.get(key);
    }
}
